#include <retro.h>
#include "player.h"
#include "player.gridmap.h"
#include "player.frame.h"

using namespace Retro::Player;
using namespace Retro::Player::Graphic;

GridMap::GridMap()
{
  mMap          = NULL;
  mLayerDisplay = NULL;
  mTexture      = NULL;
}

VOID GridMap::setMap(const Data::GridMap* iValue)
{
  SafeDelete(mLayerDisplay);

  if (mMap = iValue)
  {
    mLayerDisplay = new BOOL[mMap->getLayers()];
    memset(mLayerDisplay, TRUE, sizeof(BOOL) * mMap->getLayers());
  }
}

VOID GridMap::init(Display::DisplayDevice* iDevice)
{
  Data::Texture* wTileset = (Data::Texture*)
    Frame::get()->getProject().findResource(
    Data::ResourceTexture, mMap->getTilesetID());

  if (wTileset)
  {
    if (mTexture = iDevice->createTexture(wTileset->getPath()))
      mTexture->setResource(wTileset);
  }
}

VOID GridMap::uninit(Display::DisplayDevice* iDevice)
{
  iDevice->getBuffer().remove(mTexture);
  mTexture  = NULL;
}

VOID GridMap::render(
  Display::DisplayDevice* iDevice,
  INT iX,
  INT iY
  ) const
{
  if (!mMap || !mTexture ||
      mMap->getWidth() == 0 || mMap->getHeight() == 0 ||
      mTexture->getWidth() == 0 || mTexture->getHeight() == 0)
  {
    return;
  }

  Data::Texture* tileset  = (Data::Texture*)mTexture->getResource();
  INT& wTileSize          = tileset->getDataTileset().tileSize;

  iDevice->beginBatch(mTexture);

  INT startX  = iX < 0 ? (-iX / wTileSize) : 0;
  INT startY  = iY < 0 ? (-iY / wTileSize) : 0;
  INT endX    = (startX + 2) + iDevice->getWidth() / wTileSize;
  INT endY    = (startY + 2) + iDevice->getHeight() / wTileSize;

  if (endX > mMap->getWidth())
    endX = mMap->getWidth();

  if (endY > mMap->getHeight())
    endY = mMap->getHeight();

  for (int l = 0; l < mMap->getLayers(); ++l)
  {
    if (!mLayerDisplay[l]) continue;

    for (int x = startX; x < endX; ++x)
    for (int y = startY; y < endY; ++y)
    {
      INT texture = mMap->getGrid()[l][x + y * mMap->getWidth()].texture;

      iDevice->addBatch(
        Geom::Point::get(
        x * wTileSize + iX,
        y * wTileSize + iY),
        &Geom::Bounds::get(
        (texture * wTileSize) % mTexture->getWidth(),
        (texture * wTileSize) / mTexture->getWidth() * wTileSize,
        wTileSize,
        wTileSize),
        0xFFFFFFFF);
      }
  }
}
